<template>
  <div class="app-container">
      <el-container style="min-height:700px;height: 100%;">
        <!-- 左侧流程数据模块-->
        <el-card class="box-card" shadow="never" >
          <el-main style="padding: 0">
            <div style='position: relative;'>
              <el-tabs tab-position="top" v-model="activeName" @tab-click="handleClick">
                  <!--表单信息-->
                <el-tab-pane name="1">
                  <template #label>
                    <span class="custom-tabs-label">
                      <i class="element-icons el-icon-form"></i>
                      <span>表单信息</span>
                    </span>
                  </template>
                  <!--初始化流程加载表单信息-->
                  <el-col :span="20" :offset="2">
                    <v-form-render v-if="renderForm" :form-data="formRenderData" ref="vFormRef"/>
                    <component v-else :is="formCompName" ref="vFormRef"></component>
                  </el-col>
                </el-tab-pane>
                  <!--流程图-->
                <el-tab-pane name="2">
                  <template #label>
                    <span class="custom-tabs-label">
                      <i class="element-icons el-icon-flow"></i>
                      <span>流程图</span>
                    </span>
                  </template>
                  <bpmn-viewer :flowData="flowData"/>
                </el-tab-pane>
              </el-tabs>
              <el-button style='position: absolute;right:60px;top:5px;' size="small" class="custom-button-size" type="danger" @click="goBack">关闭</el-button>
              <el-tooltip class="item" effect="dark" placement="top">
                <template #content>{{designer ? '收起' : '展开'}}</template>
                <el-button style='position: absolute;right:10px;top:5px;' size="small" class="custom-button-size" :icon="designer ? 'DArrowRight':'DArrowLeft'" @click="togglePanel"/>
              </el-tooltip>
            </div>
          </el-main>
        </el-card>

        <!--右侧流程处理模块-->
        <el-card shadow="never" :style="designer?'width: 50%':'width: 0'">
          <template #header>
            <div class="card-header">
              <el-icon><Stamp /></el-icon> 任务申请
            </div>
          </template>
          <el-form
              label-position="top"
              label-width="100px"
              :model="taskForm"
              ref="taskFormRef"
              style="max-width: 460px"
              size="default"
          >
            <el-form-item label="申请备注" prop="comment"
                          :rules="[{ required: true, message: '请填写申请备注', trigger: 'blur' }]">
              <el-input type="textarea" :rows="3" v-model="taskForm.comment" placeholder="请填写申请备注"/>
            </el-form-item>
            <el-form-item label="操作" required>
              <el-button :loading="loading2" type="primary" size="small" class="custom-button-size" @click="handleOpenSubmitForm">提 交</el-button>
              <el-button type="info" size="small" class="custom-button-size" @click="resetForm">重 置</el-button>
              <el-button type="warning" size="small" class="custom-button-size" @click="saveDraft">暂 存</el-button>
              <el-button type="success" size="small" class="custom-button-size" @click="handleOpenDraft">草稿箱</el-button>
            </el-form-item>
          </el-form>
        </el-card>
      </el-container>

      <!--选择任务接收人-->
      <el-dialog
          title="发起任务"
          v-model="taskSubmitOpen"
          width="55%"
          :close-on-press-escape="false"
          :destroy-on-close="true"
          append-to-body
      >
        <el-form label-position="top" label-width="100px">
          <template v-for="(item, index) in nextAssignList">
            <el-form-item v-if="item.dataType === 'dynamic'" :key="index">
              <template #label>
                <i style="color:red;">*&nbsp; </i> 任务接收 ({{item.nextNodeName}})
              </template>
              <el-button round style="margin-right: 5px;margin-bottom: 5px" size="small" class="custom-button-size" type="primary" icon="Plus" @click="changeNextAssign(item)">选择任务接收</el-button>
              <el-tag
                  style="margin-right: 5px;"
                  v-for="assign in item.selectAssignList"
                  :key="assign.id"
                  closable
                  @close="removeAssign(assign, item.nextNodeId)">
                {{assign.name}}
              </el-tag>
            </el-form-item>
          </template>
        </el-form>
        <template #footer>
          <span class="dialog-footer">
            <el-button type="info" size="small" class="custom-button-size" @click="taskSubmitOpen = false">取 消</el-button>
            <el-button type="primary" size="small" class="custom-button-size" @click="submitTask">确 定</el-button>
          </span>
        </template>
      </el-dialog>

      <!--选择抄送人-->
      <el-dialog
        title="选择人员"
        v-model="copyUserOpen"
        width="60%"
        :close-on-press-escape="false"
        :destroy-on-close="true"
        :show-close="false"
    >
      <flow-users v-if="copyUserOpen" :selectData="taskForm.checkedCopyUser" @handleUserSelect="copyUserSelect"></flow-users>
      <template #footer>
        <span class="dialog-footer">
        <el-button size="small" class="custom-button-size" @click="copyUserOpen = false">取 消</el-button>
        <el-button type="primary" size="small" class="custom-button-size" @click="submitCopySelect">确 定</el-button>
        </span>
      </template>
    </el-dialog>

    <!--选择流程任务接收人-->
    <el-dialog
        title="选择任务接收"
        v-model="taskOpen"
        :width="currentType === 'dept' ? '30%' : '65%'"
        :before-close="cancelAssignSelect"
        :close-on-press-escape="false"
        :destroy-on-close="true"
        append-to-body
    >
      <component v-if="taskOpen" :is="currentComponent" :selectData="selectDataMap[nextNodeId]" @handleAssignSelect="handleAssignSelect"/>
      <template #footer>
        <span class="dialog-footer">
          <el-button size="small" class="custom-button-size" @click="cancelAssignSelect">取 消</el-button>
          <el-button type="primary" size="small" class="custom-button-size" @click="submitSelect">确 定</el-button>
        </span>
      </template>
    </el-dialog>

    <!--草稿信息-->
    <el-drawer
        title="草稿信息"
        size="47%"
        v-model="draftOpen"
        :close-on-press-escape="false"
        :destroy-on-close="true"
        direction="rtl"
        append-to-body
    >
      <el-table v-loading="loading" :data="flowDraftList">
        <el-table-column label="主键" align="center" prop="id" />
        <el-table-column label="草稿名称" align="center" prop="draftName" />
        <el-table-column label="创建时间" align="center" prop="createTime" />
        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
          <template #default="scope">
            <el-button
                link
                size="small"
                type="primary"
                icon="Promotion"
                @click="handleUseDraft(scope.row)"
            >使用</el-button>
            <el-button
                link
                size="small"
                type="danger"
                icon="Delete"
                @click="handleDeleteDraft(scope.row)"
            >删除</el-button>
          </template>
        </el-table-column>
      </el-table>

      <pagination
          layout="prev, pager, next"
          v-show="total>0"
          :total="total"
          v-model:page="queryParams.pageNum"
          v-model:limit="queryParams.pageSize"
          @pagination="getDraftList"
      />
    </el-drawer>
  </div>
</template>

<script setup name="ProcessSend">

import {definitionStart, flowXmlAndNode} from "@/api/flowable/definition";
import {flowFormData, draftList, saveDraftByStart, delDraft} from "@/api/flowable/process";
import {getNextFlowNodeByStart} from "@/api/flowable/todo";
import FlowAssignee from '@/components/Flow/Task/Assignee';
import FlowUsers from '@/components/Flow/Task/User';
import BpmnViewer from '@/components/Process/viewer';
import {StrUtil} from "@/utils/StrUtil";
import {assignSelect, setAssignComponentValue} from "@/views/flowable/common/AssignUtils";
const route = useRoute();
const {proxy} = getCurrentInstance();

// 模型xml数据
const flowData = ref({});
// 切换tab标签
const activeName = ref('1');
const formRenderData = ref({});
// 流程变量数据
const taskOpen = ref(false);
const selectDataList = ref([]);
const selectCopyDataList = ref([]);
// 填写的表单数据
const formData = ref({});
// 表单渲染器
const vFormRef = ref(null);
// 抄送人
const copyUserOpen = ref(false);
const selectCopyUserList = ref([]);
const designer = ref(true);
// 是否渲染在线表单
const renderForm = ref(true);
// 路由表单组件名称
const formCompName = ref('');
const taskSubmitOpen = ref(false);

// 用于确定当前显示的组件
const currentType = ref("");
const currentComponent = shallowRef(null);
// 下一节点ID
const nextNodeId = ref('');

// 草稿箱
const flowDraftList = ref([]);
const loading = ref(false);
const loading2 = ref(false);
const total = ref(0);
const draftOpen = ref(false);

const data = reactive({
  // 查询参数
  queryParams: {
    pageNum: 1,
    pageSize: 10,
  },
  taskForm: {
    deployId: "", // 流程定义编号
    procDefId: "",// 流程实例编号
    checkedAssignMap: {},
    checkedCopyUser: null,
    copyUser: [],
    flowParam: "", // 流程变量参数
    variables: {}, // 流程变量数据
    formData: {}  // 表单内容
  },
  nextAssignList: [], // 后续审批
  selectDataMap: {}, // 选中的审批人
});

const {queryParams, taskForm, nextAssignList, selectDataMap} = toRefs(data);

taskForm.value = route.query;
taskForm.value.checkedAssignMap = {};

getFlowFormData();

/** tab点击 */
function handleClick(tab, event) {
  if (tab.props.name === '2') {
    flowXmlAndNode(taskForm.value).then(res => {
      flowData.value = res.data;
    })
  }
}

/** 隐藏面板*/
function togglePanel() {
  designer.value = !designer.value;
}

/** 流程表单数据 */
function getFlowFormData() {
  flowFormData(taskForm.value).then(res => {
    // 加载路由表单
    if (res.data.formType === 'route') {
      // 加载路由表单
      loadRouteForm(res.data);
    } else {
      // 加载在线表单
      loadOnlineForm(res.data);
    }
  }).catch(res => {
    goBack();
  })
}

// 加载路由表单
function loadRouteForm(data) {
  renderForm.value = false;
  formCompName.value = data.formContent;
}

// 加载在线表单
function loadOnlineForm(data) {
  renderForm.value = true;
  proxy.$nextTick(() => {
    vFormRef.value.setFormJson(data.formContent);
  });
}

// 获取下一步任务节点
function nextFlowNodeByStart() {
  // 调用API获取下一步任务节点
  getNextFlowNodeByStart(taskForm.value).then(res => {
    const dataList = res?.data || [];
    nextAssignList.value = dataList.map(data => ({
      nextNodeId: data.nextNodeId,
      nextNodeName: data.nextNodeName,
      dataType: data.dataType,
      currentType: data.type === 'multiInstance'? 'users': data.type,
      flowType: data.type,
      flowParam: data.flowParam,
      selectAssignList: [],
    }));

    // 选择任务接收人或直接提交任务
    if (nextAssignList.value.length > 0){
      taskSubmitOpen.value = true;
    } else {
      submitTask();
    }
  })
}

/** 提交任务 */
function submitApplyTask() {
  definitionStart(taskForm.value).then(res => {
    proxy.$modal.msgSuccess(res.msg);
    loading2.value = false;
    goBack();
  });
}


/** 重置表单 */
function resetForm() {
  vFormRef.value.resetForm();
}

// 打开任务审批弹窗
function handleOpenSubmitForm(){
  // 获取表单数据
  vFormRef.value.getFormData().then(formData => {
    //  获取表单数据并赋值到流程变量对象中
    taskForm.value.variables = {...formData};
    // 验证表单数据是否合法
    proxy.$refs["taskFormRef"].validate(valid => {
      if (valid) {
        nextFlowNodeByStart();
      }
    })
  }).catch(error => {
    console.log(error);
  })
}

/** 提交流程 */
function submitTask() {
  loading2.value = true;
  // 获取表单数据
  vFormRef.value.getFormData().then(formData => {
    // 获取表单数据并赋值到表单数据对象中
    taskForm.value.formData = {...formData};
    //  获取表单数据并赋值到流程变量对象中
    taskForm.value.variables = {...formData};
    // 如果需要选择任务接收者但是没有选择，则提示错误信息，否则设置流程变量
    for (let i = 0; i < nextAssignList.value.length; i++) {
      const nextAssign = nextAssignList.value[i];
      if (nextAssign.dataType === 'dynamic' && StrUtil.isBlank(taskForm.value.checkedAssignMap[nextAssign.nextNodeId])) {
        proxy.$modal.msgError("请选择" + nextAssign.nextNodeName + "节点任务接收者信息!");
        return;
      }
      // 处理多实例任务,多实例任务的接收者是一个数组
      let checkedValue = taskForm.value.checkedAssignMap[nextAssign.nextNodeId];
      if (nextAssign.flowType && nextAssign.flowType === 'multiInstance') {
        checkedValue = checkedValue.split(',');
      }
      Reflect.set(taskForm.value.variables, nextAssign.flowParam, checkedValue);
    }
    // 验证表单数据是否合法
    proxy.$refs["taskFormRef"].validate(valid => {
      if (valid) {
        // 提交任务申请
        submitApplyTask();
      }
    })
  }).catch(error => {
    console.log(error);
    proxy.$modal.msgError("请完善表单信息!");
  })
}

// 处理信息选中数据
function handleAssignSelect(selection) {
  if (selection) {
    // 将选中的数据覆盖selectDataList
    selectDataList.value = JSON.parse(JSON.stringify(selection));
  }
}

// 用户选中数据
const copyUserSelect = (selection) => {
  if (selection) {
    selectCopyDataList.value = JSON.parse(JSON.stringify(selection));
  }
}

// 保存抄送选中的数据
function submitCopySelect() {
  // 如果抄送人员弹窗打开
  if (copyUserOpen.value) {
    // 将选中的数据保存到抄送人员列表中
    selectCopyUserList.value = JSON.parse(JSON.stringify(selectCopyDataList.value));
    // 将选中的抄送人员的userId保存到taskForm中
    taskForm.value.copyUser = selectCopyUserList.value.map(item => item.userId);
    // 将选中的抄送人员的userId以逗号分隔保存到taskForm中
    taskForm.value.checkedCopyUser = selectCopyUserList.value;
  }
  // 关闭抄送人员弹窗
  copyUserOpen.value = false;
}

// 保存选中的数据
function submitSelect() {
  nextAssignList.value.forEach(nextAssign => {
    if (nextAssign.nextNodeId === nextNodeId.value) {
      nextAssign.selectAssignList = JSON.parse(JSON.stringify(assignSelect(nextAssign.currentType, nextAssign.nextNodeId, selectDataList.value)));
      const checkedAssign = nextAssign.selectAssignList.map(item => item.id).join(',') || '';
      taskForm.value.checkedAssignMap[nextAssign.nextNodeId] = checkedAssign;
      if ("assignee" === nextAssign.currentType || "dept" === nextAssign.currentType) {
        selectDataMap.value[nextAssign.nextNodeId] = checkedAssign;
      } else {
        selectDataMap.value[nextAssign.nextNodeId] = nextAssign.selectAssignList
      }
    }
  });
  cancelAssignSelect();
}

// 取消审批人选择
function cancelAssignSelect(){
  taskOpen.value = false;
}

// 移除任务接收人
function removeAssign(assign, nextNodeId) {
  proxy.$confirm("确认移除该任务接收者吗？", "提示", {
    confirmButtonText: "确 认",
    cancelButtonText: "取 消"
  }).then(() => {
    nextAssignList.value.forEach(nextAssign => {
      const index = nextAssign.selectAssignList.findIndex(item => item.id === assign.id && item.nodeId === nextNodeId);
      if (index !== -1) {
        nextAssign.selectAssignList.splice(index, 1);
        const checkedAssign = nextAssign.selectAssignList.map(item => item.id).join(',') || '';
        taskForm.value.checkedAssignMap[nextAssign.nextNodeId] = checkedAssign;
        if ("assignee" === nextAssign.currentType || "dept" === nextAssign.currentType) {
          selectDataMap.value[nextAssign.nextNodeId] = checkedAssign;
        } else {
          selectDataMap.value[nextAssign.nextNodeId] = nextAssign.selectAssignList
        }
      }
    });
  }).catch(() => console.info("操作取消"));
}

// 移除抄送人员
function removeCopy(user) {
  proxy.$confirm("确认移除该抄送人员吗？", "提示", {
    confirmButtonText: "确 认",
    cancelButtonText: "取 消"
  }).then(() => {
    const index = selectCopyUserList.value.findIndex(item => item.userId === user.userId);
    if (index !== -1) {
      // 从抄送人员列表中移除该用户
      selectCopyUserList.value.splice(index, 1);
      // 更新任务表单中的抄送人员列表
      taskForm.value.copyUser = selectCopyUserList.value.map(item => item.userId);
      // 更新任务表单中的已选抄送人员
      taskForm.value.checkedCopyUser = selectCopyUserList.value;
    }
  }).catch(() => console.info("操作取消"));
}


/** 选择任务接收 */
function changeNextAssign(item){
  // 设置审批类型组件
  setAssignComponentValue(item.currentType, currentComponent);
  currentType.value = item.currentType;
  nextNodeId.value = item.nextNodeId;
  taskOpen.value = true;
}


// 打开草稿箱
function handleOpenDraft() {
  draftOpen.value = true;
  getDraftList();
}

// 获取草稿箱列表
function getDraftList() {
  loading.value = true;
  queryParams.value.deployId = taskForm.value.deployId
  draftList(queryParams.value).then(res => {
    flowDraftList.value = res.data.records;
    total.value = res.data.total;
    loading.value = false;
  })
}

// 保存草稿
function saveDraft() {
  proxy.$refs.vFormRef.getFormData().then(formData => {
    // 获取表单数据并赋值到表单数据对象中
    taskForm.value.formData = {...formData};
    //  获取表单数据并赋值到流程变量对象中
    taskForm.value.variables = {...formData};
    saveDraftByStart(taskForm.value).then(() => {
      proxy.$modal.msgSuccess('保存成功');
      goBack();
    })
  })
}

// 使用草稿
function handleUseDraft(row) {
  proxy.$refs.vFormRef.setFormData(JSON.parse(row.formContent));
  draftOpen.value = false;
}

// 删除草稿
function handleDeleteDraft(row) {
  proxy.$modal.confirm('是否确认删除编号为"' + row.id + '"的草稿？').then(function () {
    return delDraft(row.id);
  }).then(() => {
    getDraftList();
    proxy.$modal.msgSuccess('删除成功');
  }).catch(() => {});
}

/** 关闭当前标签页并返回上个页面 */
function goBack() {
  taskOpen.value = false;
  const obj = {path: "/task/mine", query: {t: Date.now()}};
  proxy.$tab.closeOpenPage(obj);
}

</script>
<style lang="scss" scoped>
.test-form {
  margin: 15px auto;
  width: 800px;
  padding: 15px;
}

.clearfix:before,
.clearfix:after {
  display: table;
  content: "";
}
.clearfix:after {
  clear: both
}

.box-card {
  width: 100%;
  margin-bottom: 20px;
}

.el-tag + .el-tag {
  margin-left: 10px;
}

.my-label {
  background: #E1F3D8;
}

.custom-tabs-label .element-icons {
  vertical-align: middle;
}
.custom-tabs-label span {
  vertical-align: middle;
  margin-left: 4px;
}
</style>
